package org.apache.database.pool;

import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import org.apache.database.entity.ConfigInfos;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

import java.sql.SQLException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class ConnectionPool {
    public  static final int POOL_CORE_SIZE=10;
    public  static final int POOL_MAX_SIZE=15;
    private static final Log log = LogFactory.getLog(ConnectionPool.class);
    /**
     * 数据了连接池
     */
    private LinkedBlockingQueue<DatabaseConnection> databaseConnectionLinkedBlockingQueue;

    /**
     * 可最大的连接
     */
    private LinkedBlockingQueue<DatabaseConnection> databaseConnectionMaxLinkedBlockingQueue;

    /**
     * 核心大小
     */
    private int poolCoreSize;

    /**
     * 允许最大
     */
    private int poolMaxSize;

    /**
     * 驱动url
     */
    private String driverUrl;

    /**
     * 数据库连接信息
     */
    private ConfigInfos configInfos;

    private ConnectionPool() {
        this.poolCoreSize = POOL_CORE_SIZE;
        this.poolMaxSize = POOL_MAX_SIZE;

    }
    private void initConnectionPool(){
        this.poolCoreSize =configInfos.getCoreConnect();
        log.info("init database pool ,size=="+poolCoreSize);
        try {
            if (configInfos.check()){
                log.error("<config error>");
                return;
            }
            Class.forName(configInfos.getDvClass());
            if (databaseConnectionLinkedBlockingQueue==null){
                databaseConnectionLinkedBlockingQueue =new LinkedBlockingQueue<>(this.poolCoreSize);
//                databaseConnectionMaxLinkedBlockingQueue =new LinkedBlockingQueue<>(this.poolMaxSize-this.poolCoreSize);
            }
            log.info("database info:"+configInfos.toString());
            for (int i = 0; i < poolCoreSize; i++) {
                databaseConnectionLinkedBlockingQueue.offer(createDatabaseConnection());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }


    /**
     * 获取一个连接
     * @return
     */
    public DatabaseConnection getConnect(){
        try {
            DatabaseConnection poll = databaseConnectionLinkedBlockingQueue.poll(5, TimeUnit.MINUTES.SECONDS);
            return poll;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 释放连接
     * @param databaseConnection
     */
    public  void releaseConnect(DatabaseConnection databaseConnection){
        try {
            if (!databaseConnection.getConnection().isClosed() && databaseConnection.getConnection().isValid(1000)){
                databaseConnectionLinkedBlockingQueue.offer(databaseConnection);
            }else {
                if (getCurrentPoolConnect()<POOL_CORE_SIZE){
                    databaseConnectionLinkedBlockingQueue.offer(createDatabaseConnection());
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
    public int getCurrentPoolConnect(){
        return databaseConnectionLinkedBlockingQueue.size();
    }
    private DatabaseConnection createDatabaseConnection(){
        return new DatabaseConnection(configInfos);
    }

    public String getDriverUrl() {
        return driverUrl;
    }

    public void setDriverUrl(String driverUrl) {
        this.driverUrl = driverUrl;
    }

    public LinkedBlockingQueue<DatabaseConnection> getDatabaseConnectionLinkedBlockingQueue() {
        return databaseConnectionLinkedBlockingQueue;
    }

    public void setDatabaseConnectionLinkedBlockingQueue(LinkedBlockingQueue<DatabaseConnection> databaseConnectionLinkedBlockingQueue) {
        this.databaseConnectionLinkedBlockingQueue = databaseConnectionLinkedBlockingQueue;
    }

    public int getPoolCoreSize() {
        return poolCoreSize;
    }

    public void setPoolCoreSize(int poolCoreSize) {
        this.poolCoreSize = poolCoreSize;
    }

    public int getPoolMaxSize() {
        return poolMaxSize;
    }

    public void setPoolMaxSize(int poolMaxSize) {
        this.poolMaxSize = poolMaxSize;
    }

    public ConfigInfos getConfigInfos() {
        return configInfos;
    }

    public void setConfigInfos(ConfigInfos configInfos) {
        this.configInfos = configInfos;
    }

    public LinkedBlockingQueue<DatabaseConnection> getDatabaseConnectionMaxLinkedBlockingQueue() {
        return databaseConnectionMaxLinkedBlockingQueue;
    }

    public void setDatabaseConnectionMaxLinkedBlockingQueue(LinkedBlockingQueue<DatabaseConnection> databaseConnectionMaxLinkedBlockingQueue) {
        this.databaseConnectionMaxLinkedBlockingQueue = databaseConnectionMaxLinkedBlockingQueue;
    }

    public static class Builder{
        private ConnectionPool connectionPool;

        public Builder() {
            connectionPool= new ConnectionPool();
        }

        public Builder setConfig(ConfigInfos c){
            connectionPool.setConfigInfos(c);
            return this;
        }
        public ConnectionPool builder(){
            connectionPool.initConnectionPool();
            return connectionPool;
        }
    }
}
